<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 
<html>
<head>
<title>Events in wxPython</title>
<link rel="stylesheet" href="/cfg/format.css" type="text/css">
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="keywords" content="wxPython, Events, programming, Python">
<meta name="description" content="This part of the wxPython tutorial covers events.">
<meta name="language" content="en">
<meta name="author" content="Jan Bodnar">
<meta name="distribution" content="global">

<script type="text/javascript" src="/lib/jquery.js"></script>
<script type="text/javascript" src="/lib/common.js"></script>

</head>

<body>

<div class="container">

<div id="wide_ad" class="ltow">
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* 160x600, August 2011 */
google_ad_slot = "2484182563";
google_ad_width = 160;
google_ad_height = 600;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>

<div class="content">


<a href="/" title="Home">Home</a>&nbsp;
<a href="..">Contents</a>


<h1>Events in wxPython</h1>

<p>
Events are integral part of every GUI application. All GUI applications are 
event-driven. An application reacts to different event types which are 
generated during its life. Events are generated mainly by the user of an 
application. But they can be generated by other means as well. e.g. internet 
connection, window manager, timer. So when we call MainLoop() method, our 
application waits for events to be generated. The MainLoop() method ends 
when we exit the application. 
</p>

<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* NewSquare */
google_ad_slot = "0364418177";
google_ad_width = 300;
google_ad_height = 250;
//-->
</script> 
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> 
</script> 

<h2>Definitions</h2>

<p>
<b>Event</b> is a piece of application-level information from the 
underlying framework, typically the GUI toolkit.
<b>Event loop</b> is  a programming construct that waits for and 
dispatches events or messages in a program. The event loop repeatedly 
looks for events to process. A <b>dispatcher</b> is a process which 
maps events to <b>event handlers</b>. Event handlers are methods 
that react to events.  
</p>


<p>
<b>Event object</b> is an object associated with the event. It is usually 
a window. <b>Event type</b> is a unique event, that has been generated. 
<b>Event binder</b> is an object, that binds an event type with an event handler.
</p>


<h2>A simple event example</h2>

<p>
In the following section we will describe a simple event. We 
will talk about a move event. 
</p>

<p>
A move event is generated, when we move a window to a new position. 
The event type is <b>wx.MoveEvent</b>. The event binder for this 
event is <b>wx.EVT_MOVE</b>
</p>


<pre class="code">
#!/usr/bin/python
# -*- coding: utf-8 -*-


import wx

class Example(wx.Frame):
           
    def __init__(self, *args, **kw):
        super(Example, self).__init__(*args, **kw) 
        
        self.InitUI()
        
        
    def InitUI(self):

        wx.StaticText(self, label='x:', pos=(10,10))
        wx.StaticText(self, label='y:', pos=(10,30))
        
        self.st1 = wx.StaticText(self, label='', pos=(30, 10))
        self.st2 = wx.StaticText(self, label='', pos=(30, 30))

        self.Bind(wx.EVT_MOVE, self.OnMove)

        self.SetSize((250, 180))
        self.SetTitle('Move event')
        self.Centre()
        self.Show(True)  

    def OnMove(self, e):
        
        x, y = e.GetPosition()
        self.st1.SetLabel(str(x))
        self.st2.SetLabel(str(y))


def main():
    
    ex = wx.App()
    Example(None)
    ex.MainLoop()    


if __name__ == '__main__':
    main()  
</pre>

<p>
The example displays the current position of the window.
</p>

<pre class="explanation">
self.Bind(wx.EVT_MOVE, self.OnMove)
</pre>

<p>
Here we bind the <code>wx.EVT_MOVE</code> event binder to the <code>OnMove()</code> method.
</p>

<pre class="explanation">
def OnMove(self, e):
    
    x, y = e.GetPosition()
    self.st1.SetLabel(str(x))
    self.st2.SetLabel(str(y))
</pre>

<p>
The event parameter in the <code>OnMove()</code> method is an object specific 
to a particular event type. In our case it is the instance of a <code>wx.MoveEvent</code> 
class. This object holds information about the event. For example the Event 
object or the position of the window. In our case the Event object is the 
wx.Frame widget. We can find out the current position by calling the 
<code>GetPosition()</code> method of the event.
</p>

<img src="/img/gui/wxpython/moveevent.png" alt="Move event">
<div class="figure">
Figure: Move event
</div>


<h2>Event binding</h2>


<p>
Working with events is straightforward in wxPython. There are three steps: 
</p>

<ul>
<li>Identify the event binder name: wx.EVT_SIZE, wx.EVT_CLOSE etc</li> 
<li>Create an event handler. It is a method, that is called, when an event is generated</li> 
<li>Bind an event to an event handler.</li> 
</ul>

<p>
In wxPython we say to bind a method to an event. 
Sometimes a word hook is used. You bind an event by calling 
the Bind() method. The method has the following parameters: 
</p>

<pre>
Bind(event, handler, source=None, id=wx.ID_ANY, id2=wx.ID_ANY)
</pre>

<ul>
<li>event is one of EVT_* objects. It specifies the type of the event.</li>
<li>handler is an object to be called. In other words, it is a method, that a programmer binds to an event. </li>
<li>source parameter is used when we want to differentiate between the same event type from different widgets. </li>
<li>id parameter is used, when we have multiple buttons, menu items etc. The id is used to differentiate among them. </li>
<li>id2 is used when it is desirable to bind a handler to a range of ids, such as with EVT_MENU_RANGE. </li>
</ul>

<p>
Note that method Bind() is defined in class EvtHandler. It is the class, 
from which wx.Window inherits. wx.Window is a base class for most widgets 
in wxPython. There is also a reverse process. If we want to unbind a 
method from an event, we call the Unbind() method. It has the 
same paremeters as the above one.
</p>


<h2>Vetoing events</h2>

<p>
Sometimes we need to stop processing an event. To do this, we call the method <i>Veto()</i>.
</p>

<pre class="code">
#!/usr/bin/python
# -*- coding: utf-8 -*-


import wx

class Example(wx.Frame):
           
    def __init__(self, *args, **kw):
        super(Example, self).__init__(*args, **kw) 
        
        self.InitUI()
                
    def InitUI(self):

        self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)

        self.SetTitle('Event veto')
        self.Centre()
        self.Show(True)

    def OnCloseWindow(self, e):

        dial = wx.MessageDialog(None, 'Are you sure to quit?', 'Question',
            wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)
            
        ret = dial.ShowModal()
        
        if ret == wx.ID_YES:
            self.Destroy()
        else:
            e.Veto()

def main():
    
    ex = wx.App()
    Example(None)
    ex.MainLoop()    


if __name__ == '__main__':
    main()  
</pre>


<p>
In our example, we process a <code>wx.CloseEvent</code>. This event is called, when we 
click the X button on the titlebar, press Alt + F4 or select close from the 
system menu. In many applications, we want to prevent from accidentally 
closing the window, if we made some changes. To do this, we must bind 
the <code>wx.EVT_CLOSE</code> event binder.
</p>

<pre class="explanation">
dial = wx.MessageDialog(None, 'Are you sure to quit?', 'Question',
    wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)
    
ret = dial.ShowModal()
</pre>

<p>
During the processing of the close event, we show a message dialog. 
</p>

<pre class="explanation">
if ret == wx.ID_YES:
    self.Destroy()
else:
    event.Veto()
</pre>

<p>
Depending on the return value from the dialog, we destroy the window, or veto the event. 
Notice that to close the window, we must call the <code>Destroy()</code> method. 
By calling the <code>Close()</code> method, we would end up in an endless cycle.
</p>


<h2>Event propagation</h2>


<p>
There are two types of events. Basic events and command events. They differ 
in propagation. Event propagation is travelling of events from child widgets 
to parent widgets and grand parent widgets etc. Basic events do not propagate. 
Command events do propagate. For example <code>wx.CloseEvent</code> is a basic event. 
It does not make sense for this event to propagate to parent widgets. 
</p>

<p>
By default, the event that is catched in a event handler stops propagating. 
To continue propagation, we must call the <code>Skip()</code> method.
</p>

<pre class="code">
#!/usr/bin/python
# -*- coding: utf-8 -*-


import wx

class MyPanel(wx.Panel):
    
    def __init__(self, *args, **kw):
        super(MyPanel, self).__init__(*args, **kw) 

        self.Bind(wx.EVT_BUTTON, self.OnButtonClicked)

    def OnButtonClicked(self, e):
        
        print 'event reached panel class'
        e.Skip()


class MyButton(wx.Button):
    
    def __init__(self, *args, **kw):
        super(MyButton, self).__init__(*args, **kw) 

        self.Bind(wx.EVT_BUTTON, self.OnButtonClicked)

    def OnButtonClicked(self, e):
        
        print 'event reached button class'
        e.Skip()
        

class Example(wx.Frame):
           
    def __init__(self, *args, **kw):
        super(Example, self).__init__(*args, **kw) 
        
        self.InitUI()
        
        
    def InitUI(self):

        mpnl = MyPanel(self)

        MyButton(mpnl, label='Ok', pos=(15, 15))

        self.Bind(wx.EVT_BUTTON, self.OnButtonClicked)

        self.SetTitle('Propagate event')
        self.Centre()
        self.Show(True)  

    def OnButtonClicked(self, e):
        
        print 'event reached frame class'
        e.Skip()


def main():
    
    ex = wx.App()
    Example(None)
    ex.MainLoop()    


if __name__ == '__main__':
    main()  
</pre>


<p>
In our example, we have a button on a panel. The panel is placed in a 
frame widget. We define a handler for all widgets. 
</p>

<pre class="explanation">
def OnButtonClicked(self, e):
    
    print 'event reached button class'
    e.Skip()
</pre>

<p>
We process the button click event in our custom button class. 
The <code>Skip()</code> method propagates the event further to
to panel class. 
</p>

<pre>
event reached button class
event reached panel class
event reached frame class
</pre>

<p>
We get this, when we click on the button. The event travels from 
the button to the panel and to the frame. 
</p>

<p>
Try to omit some Skip() methods and see, what hapens.
</p>


<h2>Window identifiers</h2>

<p>
Window identifiers are integers that uniquely determine the window 
identity in the event system. 
There are three ways to create window id's.
</p>

<ul>
    <li>let the system automatically create an id</li>
    <li>use standard identifiers</li>
    <li>create your own id</li>
</ul>

<p>
Each widget has an id parameter. This is a unique number in the event system. 
If we work with multiple widgets, we must differantiate among them.
</p>

<pre>
wx.Button(parent, -1)
wx.Button(parent, wx.ID_ANY)
</pre>

<p>
If we provide -1 or wx.ID_ANY for the id parameter, we let the wxPython 
automatically create an id for us. The automatically created id's are
always negative, whereas user specified id's must always be positive.
We usually use this option when we do not need to change the widget state. 
For example a static text, that will never be changed during the life of the 
application. We can still get the id, if we want. There is a method <code>GetId()</code>, 
which will determine the id for us.
</p>


<pre class="code">
#!/usr/bin/python
# -*- coding: utf-8 -*-


import wx

class Example(wx.Frame):
           
    def __init__(self, *args, **kw):
        super(Example, self).__init__(*args, **kw) 
        
        self.InitUI()
                
    def InitUI(self):

        pnl = wx.Panel(self)
        exitButton = wx.Button(pnl, wx.ID_ANY, 'Exit', (10, 10))

        self.Bind(wx.EVT_BUTTON,  self.OnExit, id=exitButton.GetId())

        self.SetTitle("Automatic id")
        self.Centre()
        self.Show(True)

    def OnExit(self, event):

        self.Close()

def main():
    
    ex = wx.App()
    Example(None)
    ex.MainLoop()    


if __name__ == '__main__':
    main()  
</pre>

<p>
In this example, we do not care about the actual id value. 
</p>

<pre class="explanation">
self.Bind(wx.EVT_BUTTON,  self.OnExit, id=exitButton.GetId())
</pre>

<p>
We get the automatically generated id by calling the <code>GetId()</code> method.
</p>

<hr class="btm">

<p>
It is recommended to use standard identifiers. The identifiers can 
provide some standard graphics or behaviour on some platforms. 
</p>

<pre class="code">
#!/usr/bin/python
# -*- coding: utf-8 -*-


import wx

class Example(wx.Frame):
           
    def __init__(self, *args, **kw):
        super(Example, self).__init__(*args, **kw) 
        
        self.InitUI()
                
    def InitUI(self):

        pnl = wx.Panel(self)
        grid = wx.GridSizer(3, 2)

        grid.AddMany([(wx.Button(pnl, wx.ID_CANCEL), 0, wx.TOP | wx.LEFT, 9),
            (wx.Button(pnl, wx.ID_DELETE), 0, wx.TOP, 9),
            (wx.Button(pnl, wx.ID_SAVE), 0, wx.LEFT, 9),
            (wx.Button(pnl, wx.ID_EXIT)),
            (wx.Button(pnl, wx.ID_STOP), 0, wx.LEFT, 9),
            (wx.Button(pnl, wx.ID_NEW))])

        self.Bind(wx.EVT_BUTTON, self.OnQuitApp, id=wx.ID_EXIT)

        pnl.SetSizer(grid)

        self.SetSize((220, 180))
        self.SetTitle("Standard ids")
        self.Centre()
        self.Show(True)

    def OnQuitApp(self, event):
        
        self.Close()

def main():
    
    ex = wx.App()
    Example(None)
    ex.MainLoop()    


if __name__ == '__main__':
    main()  
</pre>


<p>
In our example we use standard identifiers on buttons. On Linux, the buttons 
have icons.
</p>

<pre class="explanation">
grid.AddMany([(wx.Button(pnl, wx.ID_CANCEL), 0, wx.TOP | wx.LEFT, 9),
    (wx.Button(pnl, wx.ID_DELETE), 0, wx.TOP, 9),
    (wx.Button(pnl, wx.ID_SAVE), 0, wx.LEFT, 9),
    (wx.Button(pnl, wx.ID_EXIT)),
    (wx.Button(pnl, wx.ID_STOP), 0, wx.LEFT, 9),
    (wx.Button(pnl, wx.ID_NEW))])
</pre>

<p>
We add six buttons to a grid sizer. The wx.ID_CANCEL, wx.ID_DELETE, wx.ID_SAVE, 
wx.ID_EXIT, wx.ID_STOP and wx.ID_NEW are standard identifiers. 
</p>

<pre class="explanation">
self.Bind(wx.EVT_BUTTON, self.OnQuitApp, id=wx.ID_EXIT)
</pre>

<p>
We bind the button click event to the OnQuitApp() event handler. The
id parameter is used to differantiate among the buttons. We uniquely
identify the source of the event. 
</p>

<img src="/img/gui/wxpython/standardidentifiers.png" alt="Standard identifiers">
<div class="figure">
Figure: Standard identifiers
</div>


<hr class="btm">


<p>
The last option is to use own identifiers. We define our own global ids. 
</p>

<pre class="code">
#!/usr/bin/python
# -*- coding: utf-8 -*-


import wx

ID_MENU_NEW = wx.NewId()
ID_MENU_OPEN = wx.NewId()
ID_MENU_SAVE = wx.NewId()

class Example(wx.Frame):
           
    def __init__(self, *args, **kw):
        super(Example, self).__init__(*args, **kw) 
        
        self.InitUI()
                
    def InitUI(self):
        
        self.CreateMenuBar()
        self.CreateStatusBar()
        
        self.SetSize((250, 180))
        self.SetTitle('Global ids')
        self.Centre()
        self.Show(True)  
        
    def CreateMenuBar(self):
        
        mb = wx.MenuBar()
        
        fMenu = wx.Menu()
        fMenu.Append(ID_MENU_NEW, 'New')
        fMenu.Append(ID_MENU_OPEN, 'Open')
        fMenu.Append(ID_MENU_SAVE, 'Save')
        
        mb.Append(fMenu, '&amp;File')
        self.SetMenuBar(mb)
        
        self.Bind(wx.EVT_MENU, self.DisplayMessage, id=ID_MENU_NEW)
        self.Bind(wx.EVT_MENU, self.DisplayMessage, id=ID_MENU_OPEN)
        self.Bind(wx.EVT_MENU, self.DisplayMessage, id=ID_MENU_SAVE)        
        
    def DisplayMessage(self, e):
        
        sb = self.GetStatusBar()
                
        eid = e.GetId()
        
        if eid == ID_MENU_NEW:
            msg = 'New menu item selected'
        elif eid == ID_MENU_OPEN:
            msg = 'Open menu item selected'
        elif eid == ID_MENU_SAVE:
            msg = 'Save menu item selected'
        
        sb.SetStatusText(msg)

def main():
    
    ex = wx.App()
    Example(None)
    ex.MainLoop()    


if __name__ == '__main__':
    main()  
</pre>

<p>
In the code example, we create a menu with three menu items. The ids
for this menu items are created globally.
</p>

<pre class="explanation">
ID_MENU_NEW = wx.NewId()
ID_MENU_OPEN = wx.NewId()
ID_MENU_SAVE = wx.NewId()
</pre>

<p>
The <code>wx.NewId()</code> method creates a new unique id. 
</p>

<pre class="explanation">
self.Bind(wx.EVT_MENU, self.DisplayMessage, id=ID_MENU_NEW)
self.Bind(wx.EVT_MENU, self.DisplayMessage, id=ID_MENU_OPEN)
self.Bind(wx.EVT_MENU, self.DisplayMessage, id=ID_MENU_SAVE) 
</pre>

<p>
All three menu items are identified by their unique id. 
</p>

<pre class="explanation">
eid = e.GetId()

if eid == ID_MENU_NEW:
    msg = 'New menu item selected'
elif eid == ID_MENU_OPEN:
    msg = 'Open menu item selected'
elif eid == ID_MENU_SAVE:
    msg = 'Save menu item selected'
</pre>

<p>
From the event object we retrieve the id. Depending on the
id value, we prepare the message, which is displayed in the
statusbar of the application. 
</p>


<h2>PaintEvent</h2>

<p>
A paint event is generated when a window is redrawn. This happens when 
we resize a window or when we maximize it. A paint event can be generated 
programatically as well. For example, when we call SetLabel() method 
to change a <code>wx.StaticText</code> widget. Note that when we minimize 
a window, no paint event is generated.
</p>


<pre class="code">
#!/usr/bin/python
# -*- coding: utf-8 -*-


import wx

class Example(wx.Frame):
           
    def __init__(self, *args, **kw):
        super(Example, self).__init__(*args, **kw) 
        
        self.InitUI()
                
    def InitUI(self):

        self.count = 0
        self.Bind(wx.EVT_PAINT, self.OnPaint)

        self.SetSize((250, 180))
        self.Centre()
        self.Show(True)  

    def OnPaint(self, e):
        
        self.count += 1
        self.SetTitle(str(self.count))
        
def main():
    
    ex = wx.App()
    Example(None)
    ex.MainLoop()    


if __name__ == '__main__':
    main()  
</pre>


<p>
In our example we count the number of paint events and set the current number
of generated events to the title of the frame window. 
</p>

<pre class="explanation">
self.Bind(wx.EVT_PAINT, self.OnPaint)
</pre>

<p>
We bind the EVT_PAINT event to the OnPaint() method. 
</p>

<pre class="explanation">
def OnPaint(self, e):
    
    self.count += 1
    self.SetTitle(str(self.count))
</pre>

<p>
Inside the OnPaint() event, we increase the counter and set it
to the title of the frame window. 
</p>


<h2>Focus event</h2>

<p>
The focus indicates the currently selected widget in application. 
The text entered from the keyboard or pasted from the clipboard is 
sent to the widget, which has the focus. There are two event types 
concerning focus. The <code>wx.EVT_SET_FOCUS</code>
event, which is generated when a widget receives focus. The 
<code>wx.EVT_KILL_FOCUS</code> is generated, when the widget looses focus. 
The focus is changed by clicking or by a keybord key. Usually Tab/Shift+Tab.
</p>

<pre class="code">
#!/usr/bin/python
# -*- coding: utf-8 -*-


import wx

class MyWindow(wx.Panel):
    
    def __init__(self, parent):
        super(MyWindow, self).__init__(parent)

        self.color = '#b3b3b3'

        self.Bind(wx.EVT_PAINT, self.OnPaint)
        self.Bind(wx.EVT_SIZE, self.OnSize)
        self.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus)
        self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)

    def OnPaint(self, e):
        
        dc = wx.PaintDC(self)

        dc.SetPen(wx.Pen(self.color))
        x, y = self.GetSize()
        dc.DrawRectangle(0, 0, x, y)

    def OnSize(self, e):
        
        self.Refresh()

    def OnSetFocus(self, e):
        
        self.color = '#0099f7'
        self.Refresh()

    def OnKillFocus(self, e):
        
        self.color = '#b3b3b3'
        self.Refresh()

class Example(wx.Frame):
           
    def __init__(self, *args, **kw):
        super(Example, self).__init__(*args, **kw) 
        
        self.InitUI()
        
        
    def InitUI(self):

        grid = wx.GridSizer(2, 2, 10, 10)
        grid.AddMany([(MyWindow(self), 0, wx.EXPAND|wx.TOP|wx.LEFT, 9),
            (MyWindow(self), 0, wx.EXPAND|wx.TOP|wx.RIGHT, 9), 
            (MyWindow(self), 0, wx.EXPAND|wx.BOTTOM|wx.LEFT, 9), 
            (MyWindow(self), 0, wx.EXPAND|wx.BOTTOM|wx.RIGHT, 9)])


        self.SetSizer(grid)

        self.SetSize((350, 250))
        self.SetTitle('Focus event')
        self.Centre()
        self.Show(True)  

    def OnMove(self, e):
        
        print e.GetEventObject()
        x, y = e.GetPosition()
        self.st1.SetLabel(str(x))
        self.st2.SetLabel(str(y))


def main():
    
    ex = wx.App()
    Example(None)
    ex.MainLoop()    


if __name__ == '__main__':
    main()  
</pre>

<p>
In our example, we have four panels. The panel with focus is highlighted. 
</p>

<pre class="explanation">
self.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus)
self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
</pre>

<p>
We bind two focus events to event handlers. 
</p>

<pre class="explanation">
def OnPaint(self, e):
    
    dc = wx.PaintDC(self)

    dc.SetPen(wx.Pen(self.color))
    x, y = self.GetSize()
    dc.DrawRectangle(0, 0, x, y)
</pre>

<p>
In the OnPaint() method, we draw on the windows. The color of
the outline depends on whether the window has focus or not. 
The outline of the focused window is drawn in blue color. 
</p>

<pre class="explanation">
def OnSetFocus(self, e):
    
    self.color = '#0099f7'
    self.Refresh()
</pre>

<p>
In the OnSetFocus() method, we set the self.color variable
to some blue color. We refresh the frame window which will generate
a paint event for all its child widgets. The windows are redrawn and
the one with the focus has a new color for its outline. 
</p>

<img src="/img/gui/wxpython/focusevent.png" alt="Focus event">
<div class="figure">
Figure: Focus event
</div>


<h2>KeyEvent</h2>

<p>
When we press a key on our keyboard, wx.KeyEvent is generated.  This event 
is sent to the widget that has currently focus.
There are three different key handlers: 
</p>

<ul>
    <li>wx.EVT_KEY_DOWN</li> 
    <li>wx.EVT_KEY_UP</li> 
    <li>wx.EVT_CHAR</li> 
</ul>

<p>
A common request is to close application, when the Esc key is pressed.
</p>


<pre class="code">
#!/usr/bin/python
# -*- coding: utf-8 -*-


import wx

class Example(wx.Frame):
           
    def __init__(self, *args, **kw):
        super(Example, self).__init__(*args, **kw) 
        
        self.InitUI()
                
    def InitUI(self):

        pnl = wx.Panel(self)
        pnl.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
        pnl.SetFocus()

        self.SetSize((250, 180))
        self.SetTitle('Key event')
        self.Centre()
        self.Show(True)  

    def OnKeyDown(self, e):
        
        key = e.GetKeyCode()
        
        if key == wx.WXK_ESCAPE:
            
            ret  = wx.MessageBox('Are you sure to quit?', 'Question', 
                wx.YES_NO | wx.NO_DEFAULT, self)
                
            if ret == wx.YES:
                self.Close()               
        
def main():
    
    ex = wx.App()
    Example(None)
    ex.MainLoop()    


if __name__ == '__main__':
    main()  
</pre>

<p>
In this example, we process the Esc key press. A message box is shown to confirm,
whether we really want to close the application.
</p>

<pre class="explanation">
pnl.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
</pre>

<p>
We bind an event handler to the EVT_KEY_DOWN event. 
</p>

<pre class="explanation">
key = e.GetKeyCode()
</pre>

<p>
Here we get the key code of the pressed key.
</p>

<pre class="explanation">
if key == wx.WXK_ESCAPE:
</pre>

<p>
We check the key code. The Esc key has <code>wx.WXK_ESCAPE</code> code.
</p>


<p>
In this chapter, we talked about events in wxPython.
</p>


<div class="botNav, center">
<span class="botNavItem"><a href="/">Home</a></span> ‡ <span class="botNavItem"><a href="/wxpython">Contents</a></span> ‡
<span class="botNavItem"><a href="#">Top of Page</a></span>
</div>


<div class="footer">
<div class="signature">
<a href="/">ZetCode</a> last modified March 21, 2012  <span class="copyright">&copy; 2007 - 2013 Jan Bodnar</span>
</div>
</div>

</div> <!-- content-->

</div> <!-- container-->
</body>
</html>
